Add instances() API for primitive instancing#8952
Conversation
| model(model, count = 1) { | ||
| // Use _instanceCount only when count was NOT explicitly passed. | ||
| // arguments.length distinguishes model(geom) from model(geom, 1). | ||
| if (arguments.length < 2 && this._instanceCount !== undefined) { |
There was a problem hiding this comment.
It's a tad unintuitive seeing a default value for count and having this condition -- at least, it's not obvious whether or not it's included. Thoughts on leaving out the default value for count, and then we can do something like:
count = count ?? this._instanceCount ?? 1
``There was a problem hiding this comment.
I updated this to use count = count ?? this._instanceCount ?? 1; instead.
| * @method instances | ||
| * @param {Number} count number of instances to draw. Must be a positive | ||
| * integer. | ||
| * @returns {Object} an object with methods `sphere`, `box`, `plane`, |
There was a problem hiding this comment.
For TypeScript, if we just call it Object then all methods chained onto it will look like type errors. Take a look at the types added for the different p5.strands hooks in #8644, they add typedefs that add the different methods
There was a problem hiding this comment.
I did follow the pattern from #8644 and updated the typedefs, this also required a small fix in the type generator so the optional parameters are generated correctly.
| this._assert3d('instances'); | ||
|
|
||
| if (typeof count !== 'number' || !isFinite(count) || count < 1) { | ||
| console.log( |
There was a problem hiding this comment.
This should probably be an FES message so that it's disabled when FES is disabled
There was a problem hiding this comment.
updated this to use the Friendly Error System.
| '🌸 p5.js says: instances() requires a positive integer count.' + | ||
| ' Clamping to 1.' | ||
| ); | ||
| count = Math.max(1, Math.round(count) || 1); |
There was a problem hiding this comment.
is there an input where we don't just set it directly to 1 here? might be more robust to do that
There was a problem hiding this comment.
simplified this to clamp directly to 1.
| } finally { | ||
| r._instanceCount = undefined; | ||
| } | ||
| return p; |
There was a problem hiding this comment.
Is the intention to be able to chain multiple things? If so I think this return value would need to be the returned object below instead of p. If not, we probably don't need to return p (or track p at all)
There was a problem hiding this comment.
I made it a terminal draw call and removed the return value to avoid that misleading chaining behavior.
| * } | ||
| * function draw() { | ||
| * background(200); | ||
| * instances(10).sphere(20); |
There was a problem hiding this comment.
These currently all draw on top of each other since now shader is present, can we add a p5.strands shader to make use of the instances?
There was a problem hiding this comment.
updated the example to use p5.strands and instanceIndex so the instancing behavior is visible.
| * <div> | ||
| * <code> | ||
| * // Draw 10 spheres in a single instanced draw call. | ||
| * // A custom shader reads gl_InstanceID to offset each sphere. |
There was a problem hiding this comment.
We should probably use strands and not mention GLSL-specific things
There was a problem hiding this comment.
updated the wording to use the strands API.
davepagurek
left a comment
There was a problem hiding this comment.
This is looking good! I left some comments. Once the example in the docs is more complete, could we add it as a visual test in both webgl and webgpu modes to have an end-to-end test for each?
|
@davepagurek Done! I used the updated example as the basis and added the corresponding visual tests for both WebGL and WebGPU. |
davepagurek
left a comment
There was a problem hiding this comment.
Thanks for the updates! Some thoughts:
- Should the parameters be recursively passed into
convertTypeToTypeScriptto handle all the same cases there? (Does doing that break anything?) - For the visual tests to work, you'll need to run it first locally and commit the added snapshots so that CI has something to compare to in the future.
- There are some other shape drawing methods that aren't added yet, such as
plane,line, etc. Maybe worth looking through the3d_primitivesfile and seeing if anything else there should be added?
|
thanks for the quick feedback @davepagurek I pushed another update, also added the visual test snapshots this time, my bad for missing them in the previous push. I looked into the I also took another pass through |
|
Sounds good, thanks for looking into the typescript stuff! Yeah, let's see if we can support all the shapes if we can. |
|
Thanks, I updated the remaining retained-geometry shapes as well. I think that should cover everything from my side now, but happy to make any further changes if needed 🙂 |
davepagurek
left a comment
There was a problem hiding this comment.
thanks for the updates! I think we can support line and other APIs that go through begin/endShape by updating the count parameter in endShape to do what you've done for model.
As a list thing, I think we use instanceID() in some examples. If you search for instanceID() in the codebase to find those, can we update those to use your new syntax and avoid buildGeometry if they're just drawing a sphere or something to simplify them?
|
I added support for immediate mode APIs by forwarding instance count through For |
Addresses #8911
Changes
instances(count)API for primitive instancing in WebGL.sphere(),box(),plane(),ellipsoid(),cylinder(),cone(), andtorus().model(geometry, count)behavior while supportinginstances(count).model(geometry)p5.strandsandinstanceIndex().PR Checklist
npm run lintpasses